package com.dpiinc.TechPage.repository
import androidx.annotation.MainThread
import androidx.lifecycle.Transformations
import androidx.paging.LivePagedListBuilder
import androidx.paging.PagedList
import com.dpiinc.TechPage.api.NoteListApi
import com.dpiinc.TechPage.room.RoomAiWriterDatabase
import com.dpiinc.TechPage.room.bean.LabelEntity
import com.dpiinc.TechPage.room.bean.NoteEntity
import java.util.concurrent.Executors

/**
 * Repository implementation that returns a Listing that loads data directly from the network
 * Created by X on 2018/7/28.
 */
class SearchNoteRepository(
        private val db: RoomAiWriterDatabase,
        private val noteListApi: NoteListApi) {

    companion object {
        private const val DEFAULT_NETWORK_PAGE_SIZE = 20
    }

    // thread pool used for disk access
    @Suppress("PrivatePropertyName")
    private val diskIOExecutor = Executors.newSingleThreadExecutor()

    // thread pool used for network requests
    @Suppress("PrivatePropertyName")
    private val NETWORK_IO = Executors.newFixedThreadPool(5)

    @MainThread
    fun search(keyword: String, searchType: Int): Listing<NoteEntity> {
        val sourceFactory = SearchNoteSourceFactory(noteListApi, keyword, searchType, NETWORK_IO)
        val pagedListConfig = PagedList.Config.Builder()
                .setEnablePlaceholders(true)
                .setInitialLoadSizeHint(DEFAULT_NETWORK_PAGE_SIZE)
                .setPageSize(DEFAULT_NETWORK_PAGE_SIZE)
                .build()
        val pagedList = LivePagedListBuilder(sourceFactory, pagedListConfig)
                // provide custom executor for network requests, otherwise it will default to
                // Arch Components' IO pool which is also used for disk access
                .setFetchExecutor(NETWORK_IO)
                .build()

        val refreshState = Transformations.switchMap(sourceFactory.sourceLiveData) {
            it.initialLoad
        }
        return Listing(
                totalCount = Transformations.switchMap(sourceFactory.sourceLiveData, {
                    it.totalCount
                }),
                pagedList = pagedList,
                networkState = Transformations.switchMap(sourceFactory.sourceLiveData, {
                    it.networkState
                }),
                retry = {
                    sourceFactory.sourceLiveData.value?.retryAllFailed()
                },
                refresh = {
                    sourceFactory.sourceLiveData.value?.invalidate()
                },
                refreshState = refreshState
        )
    }

    fun loadLabels(): List<LabelEntity> {
        return db.labelDao().getLabels()
    }
}

